package com.squareup.picasso;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;

final class MarkableInputStream extends InputStream {
    private final InputStream in;
    private long offsetLimit;
    private long reset;
    private long limit;
    private long defaultMark = -1;


    public MarkableInputStream(InputStream in) {
        if (!in.markSupported()) {
            in = new BufferedInputStream(in, 4096);
        }
        this.in = in;
    }

    public final long savePosition(int readLimit) {
        long offsetLimit = this.offsetLimit + (long) readLimit;
        if (this.limit < offsetLimit) {
            try {
                if (this.reset >= this.offsetLimit || this.offsetLimit > this.limit) {
                    this.reset = this.offsetLimit;
                    this.in.mark(((int) (offsetLimit - this.offsetLimit)));
                } else {
                    this.in.reset();
                    this.in.mark(((int) (offsetLimit - this.reset)));
                    this.skip(this.reset, this.offsetLimit);
                }

                this.limit = offsetLimit;
            } catch (IOException e) {
                throw new IllegalStateException("Unable to mark: " + e);
            }
        }

        return this.offsetLimit;
    }

    public final void reset(long token) throws IOException {
        if (this.offsetLimit <= this.limit && token >= this.reset) {
            this.in.reset();
            this.skip(this.reset, token);
            this.offsetLimit = token;
            return;
        }

        throw new IOException("Cannot reset");
    }

    private void skip(long current, long target) throws IOException {
        while (current < target) {
            long skipped = this.in.skip(target - current);
            if (skipped == 0) {
                if (this.read() != -1) {
                    skipped = 1;
                } else {
                    return;
                }
            }
            current += skipped;
        }
    }

    public final int available() throws IOException {
        return this.in.available();
    }

    public final void close() throws IOException {
        this.in.close();
    }

    public final void mark(int arg3) {
        this.defaultMark = this.savePosition(arg3);
    }

    public final boolean markSupported() {
        return this.in.markSupported();
    }

    public final int read() throws IOException {
        int len = this.in.read();
        if (len != -1) {
            ++this.offsetLimit;
        }
        return len;
    }

    public final int read(byte[] bytes) throws IOException {
        int len = this.in.read(bytes);
        if (len != -1) {
            this.offsetLimit += ((long) len);
        }
        return len;
    }

    public final int read(byte[] b, int offset, int len) throws IOException {
        int readLength = this.in.read(b, offset, len);
        if (readLength != -1) {
            this.offsetLimit += ((long) readLength);
        }
        return readLength;
    }

    public final void reset() throws IOException {
        this.reset(this.defaultMark);
    }

    public final long skip(long byteCount) throws IOException {
        long skipped = this.in.skip(byteCount);
        this.offsetLimit += skipped;
        return skipped;
    }
}

